/*
   file_name :Single_improve.cc
   date_time :2025.07.13
   Comment:
      预防还未构造对象就将地址返回赋值给single，而此时有线程运行至1处判断single不为空直接返回单例实例，如果该线程调用这个单例的成员函数就会崩溃
*/

#include <iostream>
using namespace std;
#include <atomic>
#include <memory>
#include <mutex>
#include <thread>

class SingleMemoryModel
{
private:
    SingleMemoryModel()
    {
    }
    SingleMemoryModel(const SingleMemoryModel &);
    SingleMemoryModel operator=(const SingleMemoryModel &);

public:
    ~SingleMemoryModel()
    {
        std::cout << "single auto delete success" << std::endl;
    }

    static std::shared_ptr<SingleMemoryModel> GetInstance()
    {
        // 标识 single 已经初始化构造完毕
        if (_b_init.load(std::memory_order_acquire))
        {
            return single;
        }
        s_mutex.lock();
        /*
        锁的语义：mutex.lock() 和 mutex.unlock() 本身隐含了 acquire-release 语义，会强制同步内存操作。
        因此：在锁的保护下，即使第二次读取 _b_init 使用 relaxed，也能保证读到最新值。
        */
        if (_b_init.load(std::memory_order_relaxed))
        {
            s_mutex.unlock();
            return single;
        }
        single = std::shared_ptr<SingleMemoryModel>(new SingleMemoryModel);
        _b_init.store(true, std::memory_order_release);
        s_mutex.unlock();
        return single;
    }

private:
    static std::shared_ptr<SingleMemoryModel> single;
    static std::mutex s_mutex;
    static std::atomic<bool> _b_init;
};

std::shared_ptr<SingleMemoryModel> SingleMemoryModel::single = nullptr;
std::mutex SingleMemoryModel::s_mutex;
std::atomic<bool> SingleMemoryModel::_b_init = false;

void TestSingleMemory()
{
    std::thread t1([]()
                   { std::cout << "thread t1 singleton address is 0x: " << SingleMemoryModel::GetInstance() << std::endl; });

    std::thread t2([]()
                   { std::cout << "thread t2 singleton address is 0x: " << SingleMemoryModel::GetInstance() << std::endl; });

    t2.join();
    t1.join();
}

int main()
{
    TestSingleMemory();
}